/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#ifndef OBJECT_STORAGE_RESTORE_H
#define OBJECT_STORAGE_RESTORE_H

#include <mutex>
#include "obs_common/ObjectStorageCommonService.h"
#include "define/Defines.h"
#include "define/Types.h"

namespace OBSPlugin {
class ObjectStorageRestoreJob : public ObjectStorageCommonService {
public:
    ObjectStorageRestoreJob() {}
    ~ObjectStorageRestoreJob();
    EXTER_ATTACK int PrerequisiteJob() override ;
    EXTER_ATTACK int GenerateSubJob() override ;
    EXTER_ATTACK int ExecuteSubJob() override ;
    EXTER_ATTACK int PostJob() override ;

private:
    enum class MONITOR_BACKUP_RES_TYPE {
        MONITOR_BACKUP_RES_TYPE_SUCCESS          = 0,
        MONITOR_BACKUP_RES_TYPE_FAILED           = 1,
        MONITOR_BACKUP_RES_TYPE_ABORTED          = 2,
        MONITOR_BACKUP_RES_TYPE_NEEDRETRY        = 3
    };

    int PrerequisiteJobInner();
    int CreateSubJobInner(const ObjectStorageBackupSubJob& restoreSubJob);
    int PostJobInner();
    int ExecuteRestoreSubJobInner(ObjectStorageBackupSubJob restoreSubJob);
    int ExecutePrefixScanSubJob(const ObjectStorageBackupSubJob& restoreSubJob);
    int ExecuteTeardownSubJobInner();
    int ExecuteScanTeardownSubJob();
    bool InitJobInfo();
    void GetRestoreType();
    bool PrintJobInfo();
    bool InitPathForRestore();
    int UnzipPreCacheFiles(const ObjectStorageBackupSubJob& restoreSubJob);
    bool UnzipDcachefiles(const std::string& metaPath, const std::string& subfolder,
        const std::string& dcaheAndFcachePath);
    bool SetupMetaFsForRestoreJob();
    bool SetupDataFsForRestoreJob();
    bool SetupRemoteNasForRestoreJob();
    bool GetRepoPaths();
    bool GetRestoreJobInfo();
    void ClearGenerateSubJobEnv();
    void HoldScanner();
    void ReleaseScanner();
    int ProcessPrefixForScan(const PrefixInfo& prefixInfo, std::string metaPath, std::string esn);
    int GetControlFileList(std::string controlFilePath, std::vector<std::string>&  contrlFileList);
    void HandleMonitorStuck(BackupStats &backupStatistics,
        SubJobStatus::type &jobStatus, std::string &jobLogLabel, int &jobProgress);
    static void ScannerCtrlFileCallBack(void *usrData, const std::string &controlFilePath);
    static void RestoreDelCtrlCallBack(void *usrData, const std::string &controlFilePath);
    bool RetryUpdateBackupStartTime(ObjectStorageBackupSubJob& restoreSubJob);
    bool StartScanner();
    void MonitorScanner(const PrefixInfo& prefixInfo,
        SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress);
    void FillMonitorScannerVarDetails(SCANNER_TASK_STATUS &scanTaskStatus,
        SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress);
    bool HandleMonitorScannerCompletion(const PrefixInfo& prefixInfo, SubJobStatus::type &jobStatus);
    bool ReportScannerCompleteStatus(const ObjectStorageNativeScanStatistics &scanStatistics);
    void FillScanConfigBasedOnEnviroment(ScanConfig& scanConfig);
    void FillScanConfig(ScanConfig &scanConfig);
    void AddFilterRule(ScanConfig& scanConfig);
    bool InitSubJobInfo(const PrefixInfo& prefixInfo, SubJob &subJob, const std::string jobId,
        const std::string ctrlFile, uint32_t &subTaskType);
    bool StartRestore(ObjectStorageBackupSubJob restoreSubJob);
    void FillBackupCommonParams(BackupParams &backupParams);
    void FillBackupConfigPhase(BackupParams &backupParams, ObjectStorageBackupSubJob &restoreSubJob);
    void FillRestoreConfig(BackupParams &backupParams, ObjectStorageBackupSubJob &restoreSubJob);
    void FillBackupReplacePolicy(BackupParams &backupParams);
    void FillRestoreAdvanceParams(BackupParams &backupParams, ObjectStorageBackupSubJob &restoreSubJob);
    bool UpdateBackupStatistics(BackupStats &backupStatistics);
    bool CalculateJobStats();
    bool UpdateBackupStartTimeInSharedResource(ObjectStorageBackupSubJob& restoreSubJob);
    MONITOR_BACKUP_RES_TYPE MonitorRestore(BackupStats &backupStatistics,
        SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress);
    bool ReportBackupRunningStatus();
    bool ReportBackupCompletionStatus(ObjectStorageNativeBackupStats &backupStatistics);
    void RecordTimestamp();
    void RemoveCacheDirectories();
    void PrintBackupCopyInfo(ObjectStorageNativeBackupStats &backupStatistics);
    void ReportJobProgress(SubJobStatus::type &jobStatus, std::string &jobLogLabel);
    void ReportJobCompleteStatus(SubJobStatus::type &jobStatus,
        std::string &jobLogLabel, int &jobProgress);
    bool UpdateCopyPhaseStartTimeInGenRsc();
    bool GenerateSubJobList(const PrefixInfo& prefixInfo, std::vector<SubJob> &subJobList,
        std::vector<std::string> &ctrlFileList, const std::string &dstCtrlFileRelPath,
        const std::string &ctrlFileFullPath);
    bool CreateSubTasksFromCtrlFile(const PrefixInfo& prefixInfo, std::string srcDir, std::string dstDir,
        uint32_t subTaskType);
    bool UpdateGeneralInfoForCopyPhase(ObjectStorageBackupSubJob& restoreSubJob,
        ObjectStorageNativeGeneral& generalInfo);
    bool UpdateGeneralInfoForDeletePhase(ObjectStorageBackupSubJob& restoreSubJob,
        ObjectStorageNativeGeneral& generalInfo);
    void HandleMonitorComplete(SubJobStatus::type &jobStatus, std::string &jobLogLabel, int &jobProgress);
    void HandleMonitorFailed(SubJobStatus::type &jobStatus, std::string &jobLogLabel);
    void DestroyBackup();
    void HandleMonitorAbort();
    bool PreInitJobInfo();
    /* object storage */
    int GetAuthExtendInfo();
    void KeepPluginAlive();
    int HandleExecuteSubJobInner(
        BackupStats &backupStatistics, SubJobStatus::type &jobStatus, std::string &jobLogLabel);
    bool HandleSingleCopyForAggregate(uint32_t copyIndex);
    bool CreateSubJobTaskToCreateRestoreSubJob();
    bool CreateSubJobTaskToCreateRestoreSubJobInner(const std::string& esn,
        const std::string& copyId, int subTaskPrio);
    bool CreateRestoreJobTeardownTask();
    bool CreateScanJobTeardownTask();
    bool IsAggregate();
    int CheckCreateBucketExist(bool& exit);
    bool InitRepoPathsByCopyIndex(int copyIndex);
    bool GetRepoPathsWithEsn(int copyIndex, const std::string& esn,
        const std::string& pathSuffix);
    void PrintCopyPathInfo(const RepositoryDataType::type& repoType);
    uint32_t GetCopyRestoreOrder(const std::string& copyId);
    bool UpdateScanStatInfo(const PrefixInfo &prefixInfo, ObjectStorageNativeScanStatistics &scanStatistics);
    bool GetRepoEsnByExtendInfo(const std::string& exetndInfo, std::string& esn);
    bool ReportStartScanInfo();
    bool ProcessFsRelatons(BackupObjectInfosInCopy& backupObjectCopyInfo);
    bool ParseCopyExtendInfo(int copyIndex, BackupObjectInfosInCopy& backupObjectCopyInfo);
    void FillStorageConfig(Module::StorageConfig& storageConfig);
    bool IsGrainRestoreOrPermanentIncrCopy();
    void FillBackupBasedCommonParams(BackupParams &backupParams);

    bool CreateFurtherSubTasks(const ObjectStorageBackupSubJob &subJob);
    int ExecuteCreateSubJob(const ObjectStorageBackupSubJob &subJob);
    void ReportJobDetailsWithDetailAndErrcode(
    const std::tuple<JobLogLevel::type, SubJobStatus::type, const int> &reportInfo, const std::string& logLabel,
    const int64_t errCode, const std::string& message);
    void GetBackupFailDetails();

private:
    /* Restore job - control phase */
    /* Restore Job */
    std::shared_ptr<AppProtect::RestoreJob> m_restoreJobPtr {};
    std::string m_dcaheAndFcachePath;
    std::string m_preDcaheAndFcachePath;
    std::string m_scanControlFilePath;
    std::string m_restoreControlFilePath;
    std::string m_checkPointPath;
    StorageRepository m_cacheFs {};

    // key: copyId;value: map<key:esn,value: path>
    std::map<std::string, std::unordered_map<std::string, std::string>> m_dataFsPathMap;
    std::map<std::string, std::unordered_map<std::string, std::string>> m_metaFsPathMap;
    std::map<std::string, std::unordered_map<std::string, BackupObjectInfo>> m_objectInfoMap;
    std::vector<std::string> m_restoreCopyIdList; // 待恢复的副本ID列表，按恢复顺序存放
    std::string m_cacheFsPath;
    std::string m_subfolder;
    BackupObjectInfosInCopy m_backupObjectCopyInfo;
    int m_restoreJobProgress = 0;
    SubJobStatus::type m_restoreJobStatus = SubJobStatus::FAILED;
    std::string m_restoreJobLogLabel = "object_storage_plugin_restore_scan_fail_label";
    ScanStatistics m_scanStatistics {}; // 记录扫描总的统计信息

    /* Timestamp when we last attempted to send repot to GUI */
    int64_t m_lastLogReportTime {};
    bool m_isScannerRestarted {};

    /* Backup instance */
    std::unique_ptr<FS_Backup::Backup> m_backup {};
    BackupPhaseStatus m_backupStatus;

    /* SubTask type: CopyPhase/DelPhase/HardLinkPhase/DirMTimePhase */
    uint32_t m_subTaskType {};
    std::string m_esn;
    std::string m_curCopyId;

    /* Used for reporting job progress log to agent */
    ActionResult m_logResult {};
    SubJobDetails m_logSubJobDetails {};
    LogDetail m_logDetail{};
    std::vector<LogDetail> m_logDetailList;

    /* RequestId for mainJob and subJob */
    size_t m_mainJobRequestId {};
    size_t m_subJobRequestId {};
    std::atomic<bool> m_generateSubjobFinish { false };
    ObjectStorageNativeGeneral m_generalInfo {};
    ObjectStorageNativeScanStatistics m_scanStats {};
    ObjectStorageNativeBackupStats m_backupStats {};
    ObjectStorageDataLayOutExtend m_dataLayoutExt {};
    ObjectStorageTargetEnvExtend m_targetEnvExt {};
    bool m_aggregateRestore {false};
    uint32_t m_copyIndex {};
    bool m_fineGrainedRestore {false};
    std::string m_backErrMsg;
};
}
#endif // #define _NAS_SHARE_HETRO_RESTORE_H